package node;

import lexer.LexType;
import parser.Parser;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ConstInitValNode extends ASTNode {
    public final String name = "<ConstInitVal>";
    // ConstInitVal → ConstExp | '{' [ ConstExp { ',' ConstExp } ] '}' | StringConst
    private List<ConstExpNode> constExpNodes = new ArrayList<>();
    private ConstExpNode constExpNode;
    private String stringConst;

    public ConstInitValNode(List<ConstExpNode> constExpNodes) {
        this.constExpNodes = constExpNodes;
    }

    public ConstInitValNode(String stringConst) {
        this.stringConst = stringConst;
    }

    public ConstInitValNode(ConstExpNode constExpNode) {
        this.constExpNode = constExpNode;
    }

    @Override
    public void show() throws IOException {
        if (constExpNode != null) {
            constExpNode.show();
        } else if (stringConst != null) {
            Parser.parserWriter.write(LexType.STRCON + " " + stringConst + "\n");
        } else {
            Parser.parserWriter.write(LexType.LBRACE + " " + "{" + "\n");
            for (int i = 0; i < constExpNodes.size(); i++) {
                constExpNodes.get(i).show();
                if (i != constExpNodes.size() - 1) {
                    Parser.parserWriter.write(LexType.COMMA + " " + "," + "\n");
                }
            }
            Parser.parserWriter.write(LexType.RBRACE + " " + "}" + "\n");
        }
        Parser.parserWriter.write(name + "\n");
    }

    public int calculate() {
        if (constExpNode != null) {
            return constExpNode.calculate();
        } else {
            return constExpNodes.size();
        }
    }

    public List<Integer> calculateArray() {
        List<Integer> res = new ArrayList<>();
        for (ConstExpNode constExpNode : constExpNodes) {
            res.add(constExpNode.calculate());
        }
        return res;
    }

    public String calculateCharArray() {
        // 用于处理char数组
        // char数组初始化的值可能是字符串形式，也可能是字符数组形式
        // 具体来说，如果是字符串形式，那么就是一个StringConst
        // 如果是字符数组形式，那么就是多个ConstExpNode，每个ConstExpNode都是一个字符
        StringBuilder sb = new StringBuilder();
        if (stringConst != null) {
            for (int i = 1; i < stringConst.length() - 1; i++) { // 去掉首尾引号
                char c = stringConst.charAt(i);
                if (c == '\\') {
                    char next = stringConst.charAt(++i);
                    switch (next) {
                        case 'a':
                            sb.append('\007');
                            break;
                        case 'v':
                            sb.append('\013');
                            break;
                        case '0':
                            sb.append('\0');
                            break;
                        case 'n':
                            sb.append('\n');
                            break;
                        case 't':
                            sb.append('\t');
                            break;
                        case 'f':
                            sb.append('\f');
                            break;
                        case 'r':
                            sb.append('\r');
                            break;
                        case 'b':
                            sb.append('\b');
                            break;
                        case '\"':
                            sb.append('\"');
                            break;
                        case '\\':
                            sb.append('\\');
                            break;
                        case '\'':
                            sb.append('\'');
                            break;
                        default:
                            sb.append(next);
                            break; // 非标准转义字符
                    }
                } else {
                    sb.append(c);
                }
            }
        } else if (constExpNodes.size() > 0) {
            for (ConstExpNode constExpNode : constExpNodes) {
                sb.append((char) constExpNode.calculate());
            }
        } else {
            // 说明是空数组
            sb.append("");
        }
        return sb.toString();
    }

}
